#include "OutFormatter.h"
#include <sstream>

OutFormatter::OutFormatter(IntegerFormatter const & formatter, int value) : _formatter(formatter), _value(value)
{
}


OutFormatter::~OutFormatter(void)
{
}

std::ostream & operator<<(std::ostream & stream, OutFormatter const & formatter)
{
    std::ostringstream left;
    std::ostringstream right;
    std::ostringstream final;
    unsigned int work = formatter._value;
    int width = formatter._formatter._width;
	if(formatter._value < 0)
	{
		left <<  '-';
		work = -formatter._value;
        width--;
    }
	if(work == 0)
	{
        right << formatter._formatter.digitValue(0);
	}

	unsigned int last = 0;
	unsigned int topDigitValue = 1;

    // The value of the most significant digit is found:
	while(topDigitValue <= work && last < topDigitValue)
	{
		last = topDigitValue;
		topDigitValue*= formatter._formatter._base;
	}
	topDigitValue = last;

    // The integer is put into the stream right
	while(topDigitValue > 0)
	{
		right << formatter._formatter.digitValue(work/topDigitValue);
		work %= topDigitValue;
		topDigitValue /= formatter._formatter._base;
	}

    if(formatter._formatter._showBase)
	{
        right << '_' << formatter._formatter._base;
	}
    
    final.setf(formatter._formatter._adjustment,std::ios_base::adjustfield);
    final.fill(formatter._formatter._padding);
    if(formatter._formatter._adjustment & (std::ios_base::right | std::ios_base::left))
    {
        left << right.str();
        final.width(formatter._formatter._width);
        final << left.str();
    }
    else if(formatter._formatter._adjustment & std::ios_base::internal)
    {
        final << left.str();
        final.width(width);
        final << right.str();
    }
    else
    {
        throw std::runtime_error("Invalid state of IntegerFormatter, no adjust set");
    }

    return stream << final.str();
}